' **************
' * Listing Two
' **************
' * File    : FFT
' * Function: Demonstrates the use of the Fast Fourier Transforms
' * Date    : March 1988
' * Author  : Robert Wm. Ellis
' **********
' * Global variables

DEFDBL a, b, c, d, w, t
DEFINT i, j, k, n, s
DIM iwaveform% (255)
DIM a(520)

' Main program entry point
n= 256                                        ' Number of Point in the FFT
CALL init                                      'Set up Initial screen

' Clear the Spectrum array.
FOR i= 0 TO n*2
a(i)= 0
NEXT i

' EXAMPLE #1 - Cosine WAVE
' This example will produce a cosine wave with a fundamental frequency of 4.
' This means that there will be 4 full waveforms in the output array.
' Since the array is constructed of complex numbers ( real & imaginary part ),
' The entry into the array is made at location 8 ( +2 ).
' The imaginary parts are located in the odd indexes in the array.

a(10)= 1

' EXAMPLE #2 - Cosine WAVE
' This version of the Cosine Wave will be out of phase.
' That means that it will start in the negative portion of the output.
' a(10)= -1
' EXAMPLE #3 - Sine WAVE
' Here the imaginary portion of the frequency array is used to produce a
' sin function. A small real value is needed so that a divide by zero error
' does not occur.

' a(10)= .001
' a(9)= -1

' EXAMPLE #4 - Square WAVE
' The frequency array is filled starting at elemnet 2.
' The fundimental frequency for this square wave will be 8, so index 10 is the
' first entry point ( 8 + 2 ). Since the square wave is comprised of ODD
' harmonics, the next entry will be at ( 8 * 3 ) + 2.
' Since only 4 harmonics are used to synthesize the square wave there will be
' some ripple in the waveforms.
' The following equation is the fourier series for the square wave:

' y(t)= 2A[1/2 + (2/pi)cos(f0) - (2/3pi)cos(f3) + ...]
' a(10)= .67
' a(26)= -22
' a(42)= .12
' a(58)= -.08

' EXAMPLE #5 Triangle WAVE
' To construct a triangle waveform from the fourier series the same steps are
' taken as in the Square Wave. The coefficients for the triangle wave can be
' determined by the following Equation.
'                     2                 2

' y(t)= 2A[1/2 + (2/pi) cos(f0) + (2/3pi) cos(f3) + ...]
'

' a(10)= .4
' a(26)= .045
' a(42)= .0162







' ***********************************************************************************************
' Display the input waveform, call for the transformation between the frequency
' domain and the time domain, and display the spectrum plot of the resulting
' frequencies.
' ***********************************************************************************************

CALL plotu(a(), n, 40)
CALL fourier(a(), n, -1)
CALL plotu(a(), n, 110)
PRINT "Click Mouse Button to Exit."
WHILE MOUSE (0) <> 0
WEND    ' Clear mouse buffer
WHILE MOUSE (0) = 0
WEND    ' Await real mouse click
END

' **** end of main program
' ****************
' * Subroutine: Init
' * Function  : Setup Program
' * Inputs    :
' ****************

SUB init STATIC
CLS
PRINT PTAB(120);"Fast Fourier Transform Evaluation"
LINE(0,10)-(600,70),,b
LINE(0,40)-(600,40)
LOCATE 9,1
PRINT PTAB(220);"Spectrum Plot"
LINE(0,80)-(600,140),,b
LINE(0,110)-(600,110)
LOCATE 17,1
PRINT PTAB(220);"Wave Form Plot"
END SUB

' ***************************
' * Subroutine: Fourier
' * Function  : Performs Fast Fourier Transform
' * Inputs    : darray - data array in time or frequency
' *           : nn - Number of Data Points
' *           : isign - switch from forward or reverse transform
' ***************************
' * local integer variables
' * ii, jj, n, mmax, m, j, i, istep
' *
' * local double variables
' * wtemp, wr, wpr, wpi, wi, theta, tempr, tempi

SUB fourier ( darray(1), nn%, isign% ) STATIC
n= 2 * nn
j= 1

' ************************************************************************
' * Pre-weave butterfly operation is performed, to incoming complex array.
' ************************************************************************

FOR i= 1 TO n STEP 2
IF( j > i) THEN
tempr= darray(j)
tempi= darray(j+1)
darray(j)= darray(i)
darray(j+1)= darray(i+1)
darray(i)= tempr
darray(i+1)= tempi
END IF
m= n / 2
WHILE ( (m >=2) AND (j>m))
j= j - m
m= m / 2
WEND
j= j + m
NEXT i






' *
' * Top of secondary weave operation
' *

mmax= 2
WHILE ( n > mmax )

' *
' * Calculate fixed wieghting coefficients
' *

istep= 2 * mmax
theta= 6.28318530717959# / (isign * mmax)
wpr= -2! * (SIN(.5 * theta) * SIN(.5 * theta))
wpi= SIN(theta)
wr= 1!
wi= 0!

' ***********************************************************
' * Secondary weave operation is performed on complex array,
' * and results are multiplied by coefficients.
' ***********************************************************

FOR m= 1 TO mmax STEP 2
FOR i= m TO n STEP istep
j= i+ mmax
tempr= wr*darray(j)-wi*darray(j+1)
tempi= wr*darray(j+1)+wi*darray(j)
darray(j)= darray(i)-tempr
darray(j+1)= darray(i+1)-tempi
darray(i)= darray(i)+tempr
darray(i+1)= darray(i+1)+tempi
NEXT i

' *******************************
' * recalculate the coefficients
' *******************************

wtemp= wr
wr= wr*wpr-wi*wpi+wr
wi= wi*wpr+wtemp*wpi+wi
NEXT m
mmax= istep
WEND
END SUB

' ************************************
' Subroutine  : play
' Function    : play waveform constructed by FFT.
' Inputs      :
' ************************************

SUB play(a(1),waveform%(1)) STATIC
max= 0
FOR i= 0 TO 512 STEP 2
IF ABS(a(1))> max THEN
max= ABS(a(i))
END IF
NEXT i
scale= 127/max
FOR i= 0 TO 255
waveform%(i)= a((i+2)*2)* scale -1
NEXT i
SOUND 440,70
INPUT "Hit RETURN to hear constructed note",b
WAVE 2,waveform%
SOUND 110,70,127,2
END SUB











' *************
' * Subroutine: plotu
' * Function  : plot time domain data in waveform window
' * Inputs    :
' *************

SUB plotu(a(1),n%,offset%) STATIC

' * Find maximum value in data array for scaling factor to be applied to each
' * array element.

max= 0
FOR i= 2 TO n*2 STEP 2
IF ABS(a(i))> max THEN
max= ABS(a(i))
END IF
NEXT i
scale= -30/max
LINE (1,a(2)*scale+offset%)-(1,a(2)*scale+offset%),3
FOR i= 2 TO n*2 STEP 2
LINE-(i,a(i)*scale+offset%),3
NEXT I
END SUB 'end of subroutine wplot